﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RayTracing
{
    public class Parabaloid : Geometry
    {
        float a, b, c, d, e, f, g, h, i, j;
        P3 hpr = new P3(0, 0, 0); //Heading, Pitch, Roll

        public Parabaloid(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j)
        {
            // a x^2 + b y^2 + c z^2 + d x y + e x z + f y z + g x + h y + i z + j = 0

            this.a = a;
            this.b = b;
            this.c = c;
            this.d = d;
            this.e = e;
            this.f = f;
            this.g = g;
            this.h = h;
            this.i = i;
            this.j = j;
        }

        #region Geometry Members

        public P3 normal(P3 p)
        {
            float newx = 2 * a * p.x + d * p.y + e * p.z + g;
            float newy = 2 * b * p.y + d * p.x + f * p.z + h;
            float newz = 2 * c * p.z + e * p.x + f * p.y + i;

            return new P3(newx,newy,newz);
            
        }

        public float distance(Ray ray)
        {
            P3 Ro = ray.origin;
            P3 Rd = ray.direction;

            double x0 = Ro.x;
            double y0 = Ro.y;
            double z0 = Ro.z;

            double x1 = Rd.x;
            double y1 = Rd.y;
            double z1 = Rd.z;

            float dist1 =(float)( (-(g * x1) - 2 * a * x0 * x1 - d * x1 * y0 - h * y1 - d * x0 * y1 -
         2 * b * y0 * y1 - e * x1 * z0 - f * y1 * z0 - i * z1 - e * x0 * z1 - f * y0 * z1 -
         2 * c * z0 * z1 - Math.Sqrt((double)(Math.Pow((g * x1 + 2 * a * x0 * x1 + d * x1 * y0 + h * y1 +
         d * x0 * y1 + 2 * b * y0 * y1 + e * x1 * z0 + f * y1 * z0 + i * z1 +
         e * x0 * z1 + f * y0 * z1 + 2 * c * z0 * z1),2) -
         4 * (j + g * x0 + a * Math.Pow(x0,2) + h * y0 + d * x0 * y0 + b * Math.Pow(y0,2) + i * z0 +
         e * x0 * z0 + f * y0 * z0 + c * Math.Pow(z0,2)) * (a * Math.Pow(x1,2) + d * x1 * y1 +
         b * Math.Pow(y1,2) + e * x1 * z1 + f * y1 * z1 + c * Math.Pow(z1,2))))) /
         (2 * (a * Math.Pow(x1,2) + d * x1 * y1 + b * Math.Pow(y1,2) + e * x1 * z1 + f * y1 * z1 +
         c * Math.Pow(z1,2))));
            
            float dist2 = (float)((-(g * x1) - 2 * a * x0 * x1 - d * x1 * y0 - h * y1 - d * x0 * y1 -
         2 * b * y0 * y1 - e * x1 * z0 - f * y1 * z0 - i * z1 - e * x0 * z1 - f * y0 * z1 -
         2 * c * z0 * z1 + Math.Sqrt((double)(Math.Pow((g * x1 + 2 * a * x0 * x1 + d * x1 * y0 + h * y1 +
         d * x0 * y1 + 2 * b * y0 * y1 + e * x1 * z0 + f * y1 * z0 + i * z1 +
         e * x0 * z1 + f * y0 * z1 + 2 * c * z0 * z1),2) -
         4 * (j + g * x0 + a * Math.Pow(x0,2) + h * y0 + d * x0 * y0 + b * Math.Pow(y0,2) + i * z0 +
         e * x0 * z0 + f * y0 * z0 + c * Math.Pow(z0,2)) * (a * Math.Pow(x1,2) + d * x1 * y1 +
         b * Math.Pow(y1,2) + e * x1 * z1 + f * y1 * z1 + c * Math.Pow(z1,2))))) /
         (2 * (a * Math.Pow(x1,2) + d * x1 * y1 + b * Math.Pow(y1,2) + e * x1 * z1 + f * y1 * z1 +
         c * Math.Pow(z1,2))));

            if (dist1 < 0)
            {
                dist1 = Main.infinity;
            }
            if (dist2 < 0)
            {
                dist2 = Main.infinity;
            }

            if (dist1 < dist2)
            {
                return dist1;
            }
            else
            {
                return dist2;
            }

        }

        public P2 toP2(P3 p)
        {
            return new P2(Math.Abs(p.x),Math.Abs(p.y), 0);
        }

        #endregion
    }
}
